<?php
namespace App\Think\SdkGame;

date_default_timezone_set('PRC');

class Ray{

    // PC遊戲位址 = https://pc.raygaming.co
    // mobile遊戲位址 = https://h5.raygaming.co
    // API文档线上连结，LOGO = https://drive.google.com/drive/folders/10duz-ioTEActm1keR12Dg1n1uSrGR7xs
    // 若转帐失败或没收到回传值请一定要使用【查交易狀態】方法确认该笔转帐是否成功
    
    public function __construct()
    {
        // api地址
        $this->api_url = 'https://openapi.raygaming.co/gateway';
        $this->app_key = '8c0aff0233df109b';
        $this->app_secret = '2c55bccc91513262983ea46dda9f4e54';

        $this->plat_type = 'Ray';
        $this->game_url_mobile = 'https://h5.raygaming.co';
        $this->game_url_pc     = 'https://pc.raygaming.co';
    }

    /**
     * 注册
     */
    public function register($param){
        $req_data = array(
            'account_name' => $param['account'],
            'nickname'     => $param['account'],
            'currency' => 'CNY'
        );
        $method = 'account.register';
        $url = $this->build_request($method, $req_data);
        $res = $this->sendRequest($this->api_url, $url);
        return $res;
    }
    /**
     * 获取登录链接
     */
    public function login($param){
        // $reg_res = $this->register($param);
        // if($reg_res['code'] == -1) return $reg_res;
        $req_data = array(
            'user_name' => $param['account'],
            'lobby_url' => '',
            'iat' => strtotime('+30 min')
        );
        $url = $this->build_request("", $req_data);
        $url = http_build_query($url);

        $game_url  = $param['device']=='mobile' ? $this->game_url_mobile : $this->game_url_pc;
        $login_url = $game_url."/?".$url;

        return ['code'=>1, 'url'=>$login_url ];
    }
    /**
     * 获取余额
     */
    public function balance($param){
        $req_data = array(
            "account_name" => $param['account']
        );
        $method = 'account.balance';
        $url = $this->build_request($method, $req_data);
        $res = $this->sendRequest($this->api_url, $url);
        return [ 'code'=>$res['code'], 'balance'=>(float)$res['balance'] ];
    }
    
    /**
     * 转入资金(上分)
     */
    public function transIn($param){
        $req_data = array(
            "account_name" => $param['account'],
            "out_trade_no" => $param['orderid'],
            "amount"       => $param['money']
        );
        $method = 'account.deposit';
        $url = $this->build_request($method, $req_data);
        $res = $this->sendRequest($this->api_url, $url);
        return $res;
    }
    /**
     * 转出资金(下分)
     */
    public function transOut($param){
        $req_data = array(
            "account_name" => $param['account'],
            "out_trade_no" => $param['orderid'],
            "amount"       => $param['money']
        );
        $method = 'account.withdraw';
        $url = $this->build_request($method, $req_data);
        $res = $this->sendRequest($this->api_url, $url);
        return $res;
    }
    /**
     * 可转出资金查询(下分额度)
     */
    public function transOutInfo($param){
        $req_data = array(
            "account_name" => $param['account']
        );
        $method = 'account.balance';
        $url = $this->build_request($method, $req_data);
        $res = $this->sendRequest($this->api_url, $url);
        return $res;
    }

    /**
     * 查询玩家的上下分订单信息
     */
    // public function orderStatus($param){
    //     $req_data = array(
    //         "account" => $param['account'],
    //         "orderid" => $param['orderid'],
    //     );
    //     $url = $this->build_request(4, $req_data);
    //     $res = $this->sendRequest($this->api_url, $url);
    //     return $res;
    // }
    // /**
    //  * 玩家信息查询
    //  */
    // public function userInfo($param){
    //     $req_data = array(
    //         "account" => $param['account']
    //     );
    //     $url = $this->build_request(7, $req_data);
    //     $res = $this->sendRequest($this->api_url, $url);
    //     return $res;
    // }
    // /**
    //  * 玩家状态信息查询
    //  */
    // public function userStatus($param){
    //     $req_data = array(
    //         "account" => $param['account']
    //     );
    //     $url = $this->build_request(5, $req_data);
    //     $res = $this->sendRequest($this->api_url, $url);
    //     return $res;
    // }
    
    /**
     * 游戏注单拉取
     */
    public function gameLogSync($param){
        global $tmp_list,$tmp_raw_data;
        $res = $this->gameLogSyncHandle($param);

        $tmp_list     = array_merge((array)$tmp_list, $res['list']);
        $tmp_raw_data = array_merge((array)$tmp_raw_data, $res['raw_data']);
        if( $res['code']>0 && count($res['list']) >= 30){
            $param['page'] = $res['page']+1;
            $this->gameLogSync($param);
        }
        return ['code'=>$res['code'], 'list'=>$tmp_list, 'raw_data'=>$tmp_raw_data];
    }





    /**
     * 业务 ======== start =========//
     */
    private function bet_status($status){
        // 0=待结算,1=已结算,2=用户取消,3=无效订单,4=无结果(作废)
        $rt_status = 0;
        if($status == 0) $rt_status = 0;
        if($status == 1) $rt_status = 1;
        if($status == 2) $rt_status = 2;
        if($status == 3) $rt_status = 3;
        if($status == 4) $rt_status = 3;
        return $status;
    }

    //游戏列表
    public function game_list(){
        $list = [
            '151'      => '刀塔2',// DOTA2
            '140'      => '反恐精英',    // CS:GO -Counter Strike
            '70'       => '英雄联盟',    // LOL-League of Legends
            '74'       => '王者荣耀',    // KOG -King Of Glory
            '1072082'  => '篮球',  // Basketball
            '885709'   => '足球',  // Soccer
            '10353180' => '穿越火线',    // CF-CrossFire
            '82'       => '守望先锋',    // Overwatch
            '71'       => '星际争霸II',  // StartCraft2
            '221800'   => '火箭联盟',    // Rocket League
            '1072049'  => '彩虹六号',    // Rainbow 6
            '78'       => '炉石传说',    // Hearthstone
            '174275'   => 'NBA2K',   // NBA2K
            '6965566'  => 'FIFA',    // FIFA
            '19972'    => '魔兽争霸3',   // WOW3-Warcraft 3
            '153016'   => '使命召唤',    // COD-Call Of Duty
            '19334'    => '绝地求生',    // PUBG
            '35470352' => '实况足球',    // Pro Evolution Soccer

        ];
        return $list;
    }
    //游戏名称
    public function game_name($gameid){
        $list = $this->game_list();
        return isset($list[$gameid]) ? $list[$gameid] : '未知游戏';
    }

    //游戏注单同步处理
    private function gameLogSyncHandle($param){
        $req_data = array(
            "start_time" => strtotime($param['startTime']),
            "end_time"   => strtotime($param['endTime']),
            "settle"     => 2,
            "page"       => isset($param['page']) ? $param['page'] : 1
        );
        $method = 'order.list';
        $url = $this->build_request($method, $req_data);
        $res = $this->sendRequest($this->api_url, $url);
        //数据返回处理
        $list = @$res['data'];
        $rs = $raw_data = [];
        if(is_array($list) && count($list) > 0){
            foreach ($list as $k => $v) {
                $tmp_raw_data = $v;
                $status = $this->bet_status($v['status']);
                $money_winlose = $money_valid = 0;
                if($status == 1){
                    //计算流水&输赢
                    $money_winlose = $v['total_bonus'] > 0 ? $v['total_bonus']-$v['total_stake'] : -$v['total_stake'];
                    if($money_winlose < 0)  $money_valid = -$money_winlose;
                    if($money_winlose >= 0){
                        if($v['detail'][0]['odds'] < 1.5)  $money_valid = 0;
                        if($v['detail'][0]['odds'] >= 1.5) $money_valid = $money_winlose<$v['total_stake'] ? $money_winlose : $v['total_stake'];
                    }
                } 
                //游戏记录处理
                $rs[$k] = [
                    'plat_type'     => $this->plat_type,
                    'game_type'     => $v['detail'][0]['game_id'],
                    'game_name'     => @$this->game_name( $v['detail'][0]['game_id'] ),

                    'game_user'     => (string)$v['username'],
                    'bet_id'        => $v['order_id'],
                    'money_bet'     => $v['total_stake'],
                    'money_valid'   => $money_valid,
                    'money_winlose' => $money_winlose,
                    'money_fee'     => 0,
                    'createtime'    => (int)strtotime($v['create_time']),
                    'updatetime'    => (int)strtotime($v['settle_time']),
                    'status'        => $status,
                ];
                //源数据处理
                $raw_data[$k] = $tmp_raw_data;
                $raw_data[$k]['plat_type'] = $this->plat_type;
                $raw_data[$k]['bet_id']    = $v['order_id'];
                // $raw_data[$k]['status']    = $status;
                $raw_data[$k]['updatetime'] = (int)strtotime($v['settle_time']);
            }
        }
        $res['list'] = $rs;
        $res['raw_data']  = $raw_data;
        $res['page'] = $req_data['page'];
        unset($res['data']);
        return $res;
    }


    /**
     * --------------
     * 内部方法
     * --------------
     */
    private function sendRequest($url,$post_data=array(), $req_type=1){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        //POST
        if($req_type == 1){ 
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
        }
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $contents = curl_exec($ch);
        curl_close($ch);
        // print_r($contents);die;
        $contents = json_decode($contents, true);
        //业务处理
        $res = $contents;
        if(!isset($res['code']) || $res['code'] != 'ok'){
            $res['code'] = -1;
        }else{
            $res['code'] = 1;
        }
        return $res;
    }
    
    private function build_request($type='', array $param){
        $payload = array('app_key'=>$this->app_key, 'method'=>$type, 'data'=>$param);
        $jwt = new RayJwt();
        $token = $jwt->getToken($payload);
        return ['payload'=>$token];
    }
}


/**
 * PHP实现jwt
 */
class RayJwt {

    //头部
    private static $header=array(
        'alg'=>'HS256', //生成signature的算法
        'typ'=>'JWT'    //类型
    );

    //使用HMAC生成信息摘要时所使用的密钥
    private static $key='2c55bccc91513262983ea46dda9f4e54';

    /**
     * 获取jwt token
     * @param array $payload jwt载荷   格式如下非必须
     * [
     *  'iss'=>'jwt_admin',  //该JWT的签发者
     *  'iat'=>time(),  //签发时间
     *  'exp'=>time()+7200,  //过期时间
     *  'nbf'=>time()+60,  //该时间之前不接收处理该Token
     *  'sub'=>'www.admin.com',  //面向的用户
     *  'jti'=>md5(uniqid('JWT').time())  //该Token唯一标识
     * ]
     * @return bool|string
     */
    public static function getToken($payload)
    {
        if(is_array($payload))
        {
            $base64header=self::base64UrlEncode(json_encode(self::$header,JSON_UNESCAPED_UNICODE));
            $base64payload=self::base64UrlEncode(json_encode($payload,JSON_UNESCAPED_UNICODE));
            $token=$base64header.'.'.$base64payload.'.'.self::signature($base64header.'.'.$base64payload,self::$key,self::$header['alg']);
            return $token;
        }else{
            return false;
        }
    }

    /**
     * 验证token是否有效,默认验证exp,nbf,iat时间
     * @param string $Token 需要验证的token
     * @return bool|string
     */
    public static function verifyToken($Token)
    {
        $tokens = explode('.', $Token);
        if (count($tokens) != 3)
            return false;
        list($base64header, $base64payload, $sign) = $tokens;
        //获取jwt算法
        $base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);
        if (empty($base64decodeheader['alg']))
            return false;
        //签名验证
        if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign)
            return false;
        $payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);
        //签发时间大于当前服务器时间验证失败
        if (isset($payload['iat']) && $payload['iat'] > time())
            return false;
        //过期时间小宇当前服务器时间验证失败
        if (isset($payload['exp']) && $payload['exp'] < time())
            return false;
        //该nbf时间之前不接收处理该Token
        if (isset($payload['nbf']) && $payload['nbf'] > time())
            return false;
        return $payload;
    }

    /**
     * base64UrlEncode   https://jwt.io/  中base64UrlEncode编码实现
     * @param string $input 需要编码的字符串
     * @return string
     */
    private static function base64UrlEncode($input)
    {
        return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
    }

    /**
     * base64UrlEncode  https://jwt.io/  中base64UrlEncode解码实现
     * @param string $input 需要解码的字符串
     * @return bool|string
     */
    private static function base64UrlDecode($input)
    {
        $remainder = strlen($input) % 4;
        if ($remainder) {
            $addlen = 4 - $remainder;
            $input .= str_repeat('=', $addlen);
        }
        return base64_decode(strtr($input, '-_', '+/'));
    }

    /**
     * HMACSHA256签名   https://jwt.io/  中HMACSHA256签名实现
     * @param string $input 为base64UrlEncode(header).".".base64UrlEncode(payload)
     * @param string $key
     * @param string $alg   算法方式
     * @return mixed
     */
    private static function signature($input, $key, $alg = 'HS256')
    {
        $alg_config=array(
            'HS256'=>'sha256'
        );
        return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key,true));
    }
}


/*
//测试和官网是否匹配begin
$payload=array('app_key'=>$this->app_key,'method'=>'','data'=>[]);
$jwt = new Jwt();
$token = $jwt->getToken($payload);
echo "<pre>";
echo $token;

//对token进行验证签名
$getPayload=$jwt->verifyToken($token);
echo "<br><br>";
var_dump($getPayload);
echo "<br><br>";
//测试和官网是否匹配end


//自己使用测试begin
$payload_test=array('iss'=>'admin','iat'=>time(),'exp'=>time()+7200,'nbf'=>time(),'sub'=>'www.admin.com','jti'=>md5(uniqid('JWT').time()));;
$token_test=Jwt::getToken($payload_test);
echo "<pre>";
echo $token_test;

//对token进行验证签名
$getPayload_test=Jwt::verifyToken($token_test);
echo "<br><br>";
var_dump($getPayload_test);
echo "<br><br>";
//自己使用时候end
*/